package com.shitou.shitouproduct.service.impl;

import com.alibaba.fastjson.JSON;
import com.shitou.shitoucommons.exception.RRException;
import com.shitou.shitoucommons.opfeign.MemberFeign;
import com.shitou.shitoucommons.utils.*;
import com.shitou.shitoucommons.vo.*;
import com.shitou.shitouproduct.config.RabbitMQConfit;
import com.shitou.shitouproduct.entity.*;
import com.shitou.shitouproduct.service.*;
import com.shitou.shitouproduct.vo.*;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.shitou.shitouproduct.dao.SpuInfoDao;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;


@SuppressWarnings("all")
@Slf4j
@Service("spuInfoService")
@Transactional
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

    @Autowired
    private SkuInfoService skuInfoService;
    @Autowired
    private MemberSpuService memberSpuService;
    @Autowired
    private SpuInfoDescService spuInfoDescService;
    @Autowired
    private SpuImagesService spuImagesService;
    @Autowired
    private SkuSaleAttrValueService saleAttrValueService;
    @Autowired
    private ProductAttrValueService productAttrValueService;
    @Autowired
    private SkuImagesService skuImagesService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private BrandService brandService;
    @Autowired
    @Qualifier("RedisTemplate")
    private RedisTemplate redisTemplate;
    @Autowired
    private SpuInfoDao spuInfoDao;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private MemberFeign memberFeign;
    @Resource
    private CarouselService carouselService;
    @Resource
    private HotSpuService hotSpuService;
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );

        return new PageUtils(page);
    }


    /**
     * 构建用户商品
     * @param productInfoVo
     * @return
     * @see ProductInfoVo
     */
    @Override
    public RespBean editMemberProduct(ProductInfoVo productInfoVo) {
        System.out.println(productInfoVo);
        // 校验用户名是否合法
        CensorVo censorVo = TextCensor.TextCensor(productInfoVo.getSpuTitle() + productInfoVo.getSpuDetail());
        if (censorVo.getConclusion().equals("不合规") || censorVo.getConclusionType().equals("2")){
            throw new RRException("输入信息不合法,内有违规信息");
        }

        Date date = new Date();

        // 构建spu信息表  商品展示售卖
        SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
        spuInfoEntity.setBrandId((long) productInfoVo.getBrandId());   // 品牌id
        spuInfoEntity.setCatalogId((long) productInfoVo.getCategoryId());  // 分类id
        spuInfoEntity.setCreateTime(date);    // 创建时间
        spuInfoEntity.setUpdateTime(date);    // 修改时间
        spuInfoEntity.setSpuName(productInfoVo.getSpuTitle());   // spu名字
        spuInfoEntity.setSpuDescription(productInfoVo.getSpuDetail());   // spu商品详细介绍
        spuInfoEntity.setPublishStatus(1);   // 上架状态
        spuInfoEntity.setWeight(BigDecimal.valueOf(1.4900));   // 商品权重
        spuInfoEntity.setStatus(1);

        /**
         * 保存spu信息
         */
        baseMapper.insert(spuInfoEntity);


        // 构建sku属性表  商品展示售卖
        SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
        skuInfoEntity.setSpuId(spuInfoEntity.getId());   // 设置spu的id
        skuInfoEntity.setSkuDesc(productInfoVo.getSpuDetail());  // 设置sku详细介绍

        StringJoiner joiner = new StringJoiner(productInfoVo.getBrandSellName());
        for (AttrInfo attrInfo : productInfoVo.getAllAttr()) {
            joiner.add(attrInfo.getValue() + "-");
        }
//        skuInfoEntity.setSkuName(String.valueOf(joiner));   // 设置sku名称
        skuInfoEntity.setSkuName(productInfoVo.getBrandSellName());
        skuInfoEntity.setSkuTitle(productInfoVo.getSpuTitle());  // 设置sku标题
        skuInfoEntity.setSkuSubtitle(productInfoVo.getSpuTitle());  // 设置副标题
        skuInfoEntity.setCatalogId((long) productInfoVo.getCategoryId()); // 设置分类id
        skuInfoEntity.setBrandId((long) productInfoVo.getBrandId());  // 设置品牌id
        skuInfoEntity.setSaleCount(0L);    // 设置已经销售个数，二手物品统一为0
        skuInfoEntity.setPrice(productInfoVo.getPrice());   // 设置商品价格

        skuInfoEntity.setSkuDefaultImg("https://shitoumall-oss.oss-cn-beijing.aliyuncs.com/2023-03-12/42335822-e2fa-4a98-88ad-7f4389ed0cde_13.jpg");
        skuInfoEntity.setStatus(1);
        skuInfoEntity.setBrandSellProductName(productInfoVo.getBrandSellName());

        SkuInfoEntity skuInfoDo = skuInfoService.insert(skuInfoEntity);

        // 会员关联sku和spu表   用户会员与spu商品进行关联，因为是二手商品需要关联
        MemberSpuEntity memberSpuEntity = new MemberSpuEntity();
        memberSpuEntity.setMemberId((long) productInfoVo.getId());  // 会员id
        memberSpuEntity.setStatus(1);   //
        memberSpuEntity.setSpuId(spuInfoEntity.getId());   // spu_id
        memberSpuEntity.setSkuId(skuInfoDo.getSkuId());  // sku_id
        memberSpuService.save(memberSpuEntity);


        // 设置spuDesc表   spu的所有图片都在这里
        SpuInfoDescEntity spuInfoDescEntity = new SpuInfoDescEntity();
        spuInfoDescEntity.setSpuId(spuInfoEntity.getId());
        spuInfoDescEntity.setStatus(1);
        StringJoiner desc = new StringJoiner("");
        String[] imageUrls = productInfoVo.getImageUrls();
        for (String imageUrl : imageUrls) {
            desc.add(imageUrl + ";");
        }
        spuInfoDescEntity.setDecript(String.valueOf(desc));
        spuInfoDescService.save(spuInfoDescEntity);


        // 构建spu_img表    spu商品对于的展示图片
        SpuImagesEntity spuImagesEntity = new SpuImagesEntity();
        spuImagesEntity.setSpuId(spuInfoEntity.getId());   // spu_id
        if (productInfoVo.getImageUrls().length > 0)
            spuImagesEntity.setImgUrl(productInfoVo.getImageUrls()[0]);   // 取第一张作为spu展示图片
        spuImagesEntity.setStatus(1);
        spuImagesEntity.setDefaultImg(0);
        spuImagesEntity.setImgSort(0);
        spuImagesEntity.setImgName(productInfoVo.getSpuTitle());
        spuImagesService.save(spuImagesEntity);

        // 构建 sku_image 表
        SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
        skuImagesEntity.setSkuId(skuInfoDo.getSkuId());
        skuImagesEntity.setDefaultImg(0);
        skuImagesEntity.setImgSort(0);
        if (productInfoVo.getImageUrls().length > 0)
            skuImagesEntity.setImgUrl(productInfoVo.getImageUrls()[0]);
        skuImagesEntity.setStatus(1);
        skuImagesService.save(skuImagesEntity);


        /**
         * 与属性有关，如果属性没有值，那么直接不用弄了
         */
        if (productInfoVo.getAllAttr().length > 0) {
            // 构建sku_sale_attr_value 表    sku所对应的属性值关联表
            List<SkuSaleAttrValueEntity> saleAttrValueEntities = new ArrayList<>();
            for (AttrInfo attrInfo : productInfoVo.getAllAttr()) {
                SkuSaleAttrValueEntity temp = new SkuSaleAttrValueEntity();
                temp.setSkuId(skuInfoDo.getSkuId());
                temp.setAttrId((long) attrInfo.getId());   // attr属性id
                temp.setAttrValue(attrInfo.getValue());   // attr属性的值
                temp.setAttrName(attrInfo.getName());    // attr属性的名称
                temp.setAttrSort(0);
                temp.setStatus(1);
                saleAttrValueEntities.add(temp);
            }
            saleAttrValueService.saveBatch(saleAttrValueEntities);


            // 构建 product_attr_value 表    商品快速展示，通过和属性值一起，展示起来有特点,
            // 其实二手商品也不是很需要,, 但是可以用来做推荐
            List<ProductAttrValueEntity> productAttrValueEntityList = new ArrayList<>();
            for (AttrInfo attrInfo : productInfoVo.getAllAttr()) {
                ProductAttrValueEntity temp = new ProductAttrValueEntity();
                temp.setSpuId(spuInfoEntity.getId());
                temp.setAttrId((long) attrInfo.getId());   // attr属性id
                temp.setAttrValue(attrInfo.getValue());   // attr属性的值
                temp.setAttrName(attrInfo.getName());    // attr属性的名称
                temp.setQuickShow(0);   // 是否快速展示
                temp.setAttrSort(0);
                temp.setStatus(1);
                productAttrValueEntityList.add(temp);
            }
            productAttrValueService.saveBatch(productAttrValueEntityList);
        }
        // 设置商品的已经售卖的数量为 0
        String productToken = String.valueOf(new Sha256Hash(spuInfoEntity.getId().toString(), AllSaltEnum.SALT.getSalt()));
        redisTemplate.opsForValue().set("saleCount:" + productToken, new Integer(0));

        // 对商品访问次数进行统计，每日零点清零，每个小时进行排序推荐
        Map<String, Integer> spuCountMap = JSON.parseObject((String) redisTemplate.opsForValue().get("spuCount"), Map.class);
        if ( spuCountMap == null ){
            spuCountMap = new HashMap<String, Integer>();
        }
        spuCountMap.put(spuInfoEntity.getId().toString(), 1);
        redisTemplate.opsForValue().set("spuCount", JSON.toJSONString(spuCountMap));

        // 构建searchVo
        createSearchVo(spuInfoEntity, true);

        return RespBean.success();
    }


    /**
     * 对发布商品进行信息修改，需要判断是否已经售卖，
     * 毕竟售卖的商品你总还不能修改他的信息吧
     * @param productInfoVo
     * @return
     */
    @Override
    public RespBean updateMemberProduct(ProductInfoVo productInfoVo) {

        // 校验用户名是否合法
        CensorVo censorVo = TextCensor.TextCensor(productInfoVo.getSpuTitle() + productInfoVo.getSpuDetail());
        System.out.println(censorVo);
        if (censorVo.getConclusion().equals("不合规") || censorVo.getConclusionType().equals("2")){
            throw new RRException("输入信息不合法,内有违规信息");
        }

        // 判断用户时候越权
        if (productInfoVo.getId() == 0) {
            log.error("当前没有会员登陆");
            throw new RRException("当前没有会员登陆");
        }

        // 判断商品是否已经被售卖了
        Integer spuId = productInfoVo.getSpuId();
        String productToken = String.valueOf(new Sha256Hash(spuId.toString(), AllSaltEnum.SALT.getSalt()));
        Integer saleCount = (Integer) redisTemplate.opsForValue().get("saleCount:" + productToken);
        if ( saleCount == null || saleCount > 0) {
            log.error("当前商品已经进行售卖，更新商品失败");
            return RespBean.error("当前商品已经进行售卖，更新商品失败");
        }

        // 从数据库中获取实体类, 并进行校验
        SpuInfoEntity spuInfoDo = this.getOne(new QueryWrapper<SpuInfoEntity>().eq("id", productInfoVo.getSpuId()));
        SkuInfoEntity skuInfoDo = skuInfoService.getOne(new QueryWrapper<SkuInfoEntity>().eq("sku_id", productInfoVo.getSkuId()));
        if (spuInfoDo == null || skuInfoDo == null) {
            log.error("spu_id is exception or sku_id is exception");
            throw new RRException("spu_id is exception or sku_id is exception");
        }
        updateCategoryBrand(skuInfoDo, spuInfoDo, productInfoVo);
        updateSpuSkuInfo(skuInfoDo, spuInfoDo, productInfoVo);
        updateBrandSellName(skuInfoDo, productInfoVo);
        updateAttr(productInfoVo);

        // 构建searchVo
        createSearchVo(spuInfoDo, true);

        this.updateById(spuInfoDo);
        skuInfoService.updateById(skuInfoDo);

        // 如果该商品用于展示，那么修改热点商品和轮播图信息
        updateCarousel(spuInfoDo, 1);
        updateHotSpu(spuInfoDo, 1);

        return RespBean.success();
    }


    /**
     * 更新商品是，更新正在使用轮播图对应信息
     * @param spuInfo
     * @param status
     */
    public void updateCarousel(SpuInfoEntity spuInfo, Integer status){
        CarouselEntity carousel = carouselService.getOne(new QueryWrapper<CarouselEntity>()
                .eq("spu_id", spuInfo.getId()).eq("status", 1));
        if ( carousel != null ){
            carousel.setUpdateTime(new Date());
            carousel.setStatus(status);
            SpuImagesEntity spuImage = spuImagesService.getOne(new QueryWrapper<SpuImagesEntity>().eq("spu_id", spuInfo.getId()));
            carousel.setSpuImage(spuImage.getImgUrl());
            carouselService.updateById(carousel);
        }
    }


    /**
     * 修改商品时候，更新正在使用的热点商品
     * @param spuInfo
     * @param status
     */
    public void updateHotSpu(SpuInfoEntity spuInfo, Integer status){
        HotSpuEntity hotSpu = hotSpuService.getOne(new QueryWrapper<HotSpuEntity>()
                .eq("spu_id", spuInfo.getId()).eq("status", 1));
        if ( hotSpu != null ){
            hotSpu.setUpdateTime(new Date());
            hotSpu.setStatus(status);
            SpuImagesEntity spuImage = spuImagesService.getOne(new QueryWrapper<SpuImagesEntity>().eq("spu_id", spuInfo.getId()));
            hotSpu.setSpuTitle(spuInfo.getSpuName());
            hotSpu.setSpuDetail(spuInfo.getSpuDescription());
            hotSpuService.updateById(hotSpu);
        }
    }


    /**
     * 获得该用户发布的所有的商品
     * // 包括已经售卖出去了的，正在售卖的，上架的，下架的,,, 状态为1的
     * @param productInfoVo
     * @return
     */
    @Override
    public RespBean getProductByMember(ProductInfoVo productInfoVo) {
        // 获取该用户的所有
        List<MemberSpuEntity> memberSpuEntityList = memberSpuService.list(
                new QueryWrapper<MemberSpuEntity>().eq("member_id", productInfoVo.getId())
                        .eq("status", 1));
        if (memberSpuEntityList == null) {
            log.error("用户越权操作，拦截");
            throw new RRException("用户越权操作，拦截");
        }
        // 返回的数据封装列表
        List<AllMemberproductVo> allProductVoList = new ArrayList<>();

        for (MemberSpuEntity memberSpuEntity : memberSpuEntityList) {
            if (memberSpuEntity.getStatus() == 0) {   // 当前商品已经被删除了
                continue;
            }
            AllMemberproductVo allproductVo = new AllMemberproductVo();
            // 查询spuInfoEntity
            SpuInfoEntity spuInfo = this.getOne(new QueryWrapper<SpuInfoEntity>().eq("id", memberSpuEntity.getSpuId()));
            if (spuInfo.getStatus() == 0) {   // 当前商品已经被删除了
                continue;
            }
            allproductVo.setSpuId(spuInfo.getId());
            allproductVo.setSpuDetail(spuInfo.getSpuDescription());
            allproductVo.setSpuTitle(spuInfo.getSpuName());
            allproductVo.setPublishStatus(spuInfo.getPublishStatus());
            // 查询skuInfoEntity
            SkuInfoEntity skuInfo = skuInfoService.getOne(new QueryWrapper<SkuInfoEntity>().eq("sku_id", memberSpuEntity.getSkuId()));
            if (skuInfo.getStatus() == 0) {   // 当前商品已经被删除了
                continue;
            }
            allproductVo.setSkuId(skuInfo.getSkuId());
            allproductVo.setSpuPrice(skuInfo.getPrice());
            boolean sellStatus = true;   // 默认售卖了已经
            String productToken = String.valueOf(new Sha256Hash(memberSpuEntity.getSpuId().toString(), AllSaltEnum.SALT.getSalt()));
            Integer saleCount = (Integer) redisTemplate.opsForValue().get("saleCount:" + productToken);

            if (saleCount == null ){
                sellStatus = true;
            // 如果售卖的个数为 0，那么说明没有出售过，redis中的商品也要为0 哦
            } else if ( saleCount == 0 && skuInfo.getSaleCount() == 0) {
                sellStatus = false;
            }

            allproductVo.setSellStatus(sellStatus);
            // 查询spuInfoImage
            SpuImagesEntity spuImages = spuImagesService.getOne(new QueryWrapper<SpuImagesEntity>()
                    .eq("spu_id", memberSpuEntity.getSpuId())
                    .eq("status", 1));
            allproductVo.setSpuImage(spuImages.getImgUrl());

            allProductVoList.add(allproductVo);
        }

        return RespBean.success().put("data", allProductVoList);
    }


    /**
     * 通过spu_id获取单个商品信息，
     *      该接口主要用于商品的展示，所以不用判断库存
     * @param infoVo
     * @return
     */
    @Override
    public RespBean getProductBySpuId(ProductInfoVo infoVo) {
        long spuId = infoVo.getSpuId();
        // 传给前端单个商品的信息
        ProductInfoVo productInfoVo = new ProductInfoVo();
        SpuInfoEntity spuInfoDo = this.getOne(new QueryWrapper<SpuInfoEntity>().eq("id", spuId));
        if (spuInfoDo == null) {
            log.error("spu_id is exception at getProductBySpuId");
            throw new RRException("spu_id is exception at getProductBySpuId");
        }
        // 获取sku的信息
        SkuInfoEntity skuInfoDo = skuInfoService.getOne(new QueryWrapper<SkuInfoEntity>().eq("spu_id", spuId)
                .eq("status", 1));
        List<SkuSaleAttrValueEntity> saleAttrValueEntityList = saleAttrValueService.list(
                new QueryWrapper<SkuSaleAttrValueEntity>().eq("sku_id", skuInfoDo.getSkuId())
                        .eq("status", 1));
        SpuInfoDescEntity spuInfoDescEntityDo = spuInfoDescService.getOne(new QueryWrapper<SpuInfoDescEntity>()
                .eq("spu_id", spuId).eq("status", 1));

        // 设置productVo的属性
        productInfoVo.setCategoryId(Math.toIntExact(spuInfoDo.getCatalogId()));  // 分类id
        productInfoVo.setBrandId(Math.toIntExact(spuInfoDo.getBrandId()));  // brand_id
        productInfoVo.setSpuTitle(spuInfoDo.getSpuName());    // spu标题
        productInfoVo.setSpuDetail(spuInfoDo.getSpuDescription());   // spu详细介绍
        productInfoVo.setPrice(skuInfoDo.getPrice());       // 设置spu的价格
        productInfoVo.setSpuId((int) spuId);                 // 设置spu的id
        productInfoVo.setSkuId(Math.toIntExact(skuInfoDo.getSkuId()));   // 设置sku的id
        AttrInfo[] allAttr = new AttrInfo[saleAttrValueEntityList.size()];
        for (int i = 0; i < saleAttrValueEntityList.size(); i++) {
            AttrInfo attrInfo = new AttrInfo();
            // 如果该属性的值没有选中，那么就丢弃
            if (saleAttrValueEntityList.get(i).getAttrValue().equals("")) {
                continue;
            }
            // 如果该属性已经被禁用，也丢弃
            if (saleAttrValueEntityList.get(i).getStatus() != 1) {
                continue;
            }
            attrInfo.setId(Math.toIntExact(saleAttrValueEntityList.get(i).getAttrId()));
            attrInfo.setName(saleAttrValueEntityList.get(i).getAttrName());
            attrInfo.setValue(saleAttrValueEntityList.get(i).getAttrValue());
            allAttr[i] = attrInfo;
        }
        // 设置所有的属性
        productInfoVo.setAllAttr(allAttr);
        String[] split = spuInfoDescEntityDo.getDecript().split(";");
        productInfoVo.setImageUrls(split);   // 设置该商品的所有图片
        productInfoVo.setBrandSellName(skuInfoDo.getBrandSellProductName());

        CategoryEntity category = categoryService.getOne(new QueryWrapper<CategoryEntity>()
                .eq("category_id", spuInfoDo.getCatalogId()).eq("status", 1));
        if ( category == null ){
            throw new RRException("获取分类信息错误");
        }
        // 获得父亲id和当前分类的名称
        productInfoVo.setParentCid(Math.toIntExact(category.getParentCid()));
        productInfoVo.setName(category.getName());


        return RespBean.success().put("data", productInfoVo);
    }


    /**
     * 要的就是多次校验
     * @param productInfoVo 从里面获取 用户id，商品id 和状态
     * @return
     */
    @Override
    public RespBean updatePublishStatus(ProductInfoVo productInfoVo) {
        // 判断该商品是否属于该用户
        MemberSpuEntity one = memberSpuService.getOne(new QueryWrapper<MemberSpuEntity>()
                .eq("member_id", productInfoVo.getId()).eq("spu_id", productInfoVo.getSpuId()));
        if (one == null) {
            log.error("越权操作");
            throw new RRException("越权操作");
        }

        // 获得商品信息
        SpuInfoEntity spuInfo = this.getOne(new QueryWrapper<SpuInfoEntity>().eq("id", productInfoVo.getSpuId()));
        if (spuInfo == null) {
            log.error("spu_id is exception at updatePublicStatus");
            throw new RRException("spu_id is exception at updatePublicStatus");
        }
        // 由于数据在前台的时候，如果不刷新，那么你不知道商品是否被购买，所以在修改的时候，也要判断库存是否够
        // 从redis中判断库存是否充足
        Integer spuId = productInfoVo.getSpuId();
        String productToken = String.valueOf(new Sha256Hash(spuId.toString(), AllSaltEnum.SALT.getSalt()));
        // 设置所有的商品售卖的个数，存入redis中，如果不为0，那么已经出售了，对于二手商品而言，大于0就是售罄
        Integer saleCount = (Integer) redisTemplate.opsForValue().get("saleCount:" + productToken);
        if (saleCount == null || saleCount > 0) {
            // 库存不够，已经被他们买走了噶，设置商品下架
            // 设置下架
            spuInfo.setPublishStatus(0);  // 设置状态未0，【0-下架，1-上架】
            // 将索引中的状态设置为   启用
            rabbitTemplate.convertAndSend("PRODUCT-SELL-QUEUE", spuId);
            return RespBean.error();
        }

        int publishStatus = productInfoVo.getPublishStatus();
        if ( publishStatus == 1){
            // 将索引中的状态设置为   启用
            rabbitTemplate.convertAndSend("PRODUCT-RELEASE-QUEUE", spuId);
        }else {
            // 将索引中的状态设置为   不启用
            rabbitTemplate.convertAndSend("PRODUCT-SELL-QUEUE", spuId);
        }


        // 然后就是正常的上下架
        spuInfo.setPublishStatus(publishStatus);
        this.updateById(spuInfo);
        // 如果该商品用于展示，那么修改热点商品和轮播图信息
        updateCarousel(spuInfo, publishStatus);
        updateHotSpu(spuInfo, publishStatus);

        return RespBean.success();
    }


    /**
     * 获得所有商品的接口，用以给前端进行展示是
     * qps: 1460
     * @return
     */
    @Override
    public RespBean getAllProduct() {

        // 由于这个数据会比较多，且不经常变动，将商品进行静态化处理，设置过期时间为半小时
        String jaonString = (String) redisTemplate.opsForValue().get("allProduct");
        if (jaonString != null && !jaonString.equals("")) {
            List<AllProductVo> allProduct = (List<AllProductVo>) JSON.parseArray(jaonString, AllProductVo.class);
            if (allProduct != null && allProduct.size() > 0) {
                return RespBean.success().put("data", allProduct);
            }
        }
        List<AllProductVo> allProductVoList = new ArrayList<>();
        // 获取所有的spuInfo
        List<SpuInfoEntity> list = this.list(new QueryWrapper<SpuInfoEntity>().eq("publish_status", 1));
        if (list == null || list.size() == 0) {
            log.info("获取的spuInfo为空");
            throw new RRException("获取的商品信息为空");
        }

        AllProductVo productVo = null;
        Iterator<SpuInfoEntity> iterator = list.iterator();
        while (iterator.hasNext()) {
            SpuInfoEntity spuInfo = iterator.next();
            // 调用封装好的函数进行数据的组装
            AllProductVo product = getProduct(spuInfo, iterator);
            if (product == null) continue;
            productVo = product;
            allProductVoList.add(productVo);
        }
        String jsonString = JSON.toJSONString(allProductVoList);
        // redis中的数据过期或者第一次访问
        redisTemplate.opsForValue().set("allProduct", jsonString, 10, TimeUnit.SECONDS);
        return RespBean.success().put("data", allProductVoList);
    }


    /**
     * 获得单个商品的 接口
     * @param spuId
     * @return
     */
    @Override
    public RespBean getProduct(long spuId) {
        SpuInfoEntity spuInfo = this.getOne(new QueryWrapper<SpuInfoEntity>().eq("id", spuId));
        return RespBean.success().put("data", getProduct(spuInfo, null));
    }


    /**
     * 获得一个商品，封装过的，方便其他接口调用的方法v
     * @param spuInfo
     * @param list
     * @return
     */
    public AllProductVo getProduct(SpuInfoEntity spuInfo, Iterator<SpuInfoEntity> list) {

        AllProductVo productVo = new AllProductVo();
        // 获取sku信息，并剔除已经售罄的商品，
        SkuInfoEntity skuInfo = skuInfoService.getOne(
                new QueryWrapper<SkuInfoEntity>().eq("spu_id", spuInfo.getId()).eq("status", 1));
        // 剔除已经售罄的商品====!!!魔法数字丛生,,,当前已经售卖的个数，必须为0才可以
        String productToken = String.valueOf(new Sha256Hash(spuInfo.getId().toString(), AllSaltEnum.SALT.getSalt()));
        Integer saleCount = (Integer) redisTemplate.opsForValue().get("saleCount:" + productToken);

        if ( saleCount == null ){
            if ( list != null ){
                list.remove();
            }
            return null;
        }
        // 移除商品，当list不为空，且商品数据库已经售卖了0个
        if (list != null && skuInfo.getSaleCount() != 0 || saleCount != 0) {
            if ( list == null ){
                return null;
            }
            list.remove();
            return null;
        }
        // 获取商品的封面！！！哈哈哈
        SpuImagesEntity spuImagesEntity = spuImagesService.getOne(
                new QueryWrapper<SpuImagesEntity>().eq("spu_id", spuInfo.getId()).eq("status", 1));
        // 获取商品的所有图片
        SpuInfoDescEntity spuInfoDescEntity = spuInfoDescService.getOne(
                new QueryWrapper<SpuInfoDescEntity>().eq("spu_id", spuInfo.getId()).eq("status", 1));
        List<SkuSaleAttrValueEntity> saleAttrValueEntityList = saleAttrValueService.list(
                new QueryWrapper<SkuSaleAttrValueEntity>().eq("sku_id", skuInfo.getSkuId()).eq("status", 1));
        // 封装返回值
        productVo.setSpuId(spuInfo.getId());
        productVo.setSpuDetail(spuInfo.getSpuDescription());
        productVo.setSpuTitle(spuInfo.getSpuName());
        productVo.setSpuImage(spuImagesEntity.getImgUrl());
        productVo.setSkuId(skuInfo.getSkuId());
        // 所有的图片列表封装
        String decript = spuInfoDescEntity.getDecript();
        if (decript != null) {
            String[] split = decript.split(";");
            productVo.setImageUrls(split);
        }
        productVo.setSpuPrice(skuInfo.getPrice());
        AttrInfo[] attrInfos = new AttrInfo[saleAttrValueEntityList.size()];
        int index = -1;
        // 封装所有的属性值
        for (SkuSaleAttrValueEntity saleAttrValueEntity : saleAttrValueEntityList) {
            AttrInfo attrInfo = new AttrInfo();
            attrInfo.setId(Math.toIntExact(saleAttrValueEntity.getId()));
            attrInfo.setName(saleAttrValueEntity.getAttrName());
            attrInfo.setValue(saleAttrValueEntity.getAttrValue());
            attrInfos[++index] = attrInfo;
        }
        productVo.setAttrInfos(attrInfos);
        MemberSpuEntity memberSpu = memberSpuService.getOne(new QueryWrapper<MemberSpuEntity>().eq("spu_id", spuInfo.getId()));
        Long memberId = memberSpu.getMemberId();
        productVo.setMemberId(memberId);

        return productVo;
    }


    /**
     * 远程调用的方法，判断商品的当前状态
     * @param spuIds
     * @return
     */
    @Override
    public RespBean checkSaleCount(long[] spuIds) {
        long[] data = new long[spuIds.length];
        int index = -1;
        for (long spuId : spuIds) {
            SkuInfoEntity skuInfo = skuInfoService.getOne(new QueryWrapper<SkuInfoEntity>().eq("spu_id", spuId));
            SpuInfoEntity spuInfo = this.getOne(new QueryWrapper<SpuInfoEntity>().eq("id", spuId));
            if (spuId == 0 && skuInfo == null || spuInfo == null) {
                continue;
            }
            String productToken = String.valueOf(new Sha256Hash(spuInfo.getId().toString(), AllSaltEnum.SALT.getSalt()));
            Integer saleCount = (Integer) redisTemplate.opsForValue().get("saleCount:" + productToken);

            // 如果商品已经被删除，一律展示为 商品已下架
            if ( saleCount == null ){
                data[++index] = ProductStatusEnum.SALE_NOT_PUBLISH.getCode();
            }else if (skuInfo != null && spuInfo != null ) {
                // 判断商品处于上架且未售卖 [-1-商品异常，1-可购买，2-已售罄，3-商品已下架]
                int tag = -1;   // 初始化，商品异常
                // 商品 未出售且商品处于上架情况
                if ( saleCount == 0 && spuInfo.getPublishStatus() == 1) {
                    tag = ProductStatusEnum.NOT_SALE_PUBLISH.getCode();
                    // 商品 因售罄而下架
                } else if ( saleCount != 0 && spuInfo.getPublishStatus() == 0) {
                    tag = ProductStatusEnum.SALE_NOT_PUBLISH.getCode();
                    // 商品 因未出售而下架
                } else if ( saleCount == 0 && spuInfo.getPublishStatus() == 0) {
                    tag = ProductStatusEnum.NOT_SALE_NOT_PUBLISH.getCode();
                } else if ( saleCount != 0 && spuInfo.getPublishStatus() != 0 ) {
                    tag = ProductStatusEnum.SALE_NOT_PUBLISH.getCode();
                }
                // 商品被删除
                if (spuInfo.getStatus() == 0) {
                    tag = ProductStatusEnum.NOT_SALE_NOT_PUBLISH.getCode();
                }
                data[++index] = tag;
            } else {
                data[++index] = ProductStatusEnum.NOT_SALE_NOT_PUBLISH.getCode();
            }
        }
        String s = JSON.toJSONString(data);

        return RespBean.success().put("data", s);
    }


    /**
     * 逻辑删除
     * @param spuId
     * @param memberId
     * @return
     */
    @Override
    public RespBean logicDeleteProduct(long spuId, long memberId) {
        MemberSpuEntity memberSpuDo = memberSpuService.getOne(new QueryWrapper<MemberSpuEntity>().eq("member_id", memberId)
                .eq("spu_id", spuId));
        if (memberSpuDo == null) {
            log.error("商品信息错误");
            throw new RRException("商品信息错误");
        }
        memberSpuDo.setStatus(0);
        memberSpuService.updateById(memberSpuDo);

        // 更新spuInfo表
        SpuInfoEntity spuInfo = this.getOne(new QueryWrapper<SpuInfoEntity>().eq("id", spuId));
        spuInfo.setStatus(0);
        this.updateById(spuInfo);

        // 将elasticsearch的该文档设置为不可用，不启用
        createSearchVo(spuInfo, false);

        // 如果该商品用于展示，那么修改热点商品和轮播图信息
        updateCarousel(spuInfo, 0);
        updateHotSpu(spuInfo, 0);

        // 更新spu—img-desc
//        SpuInfoDescEntity spuInfoDescEntity = spuInfoDescService.getOne(new QueryWrapper<SpuInfoDescEntity>().eq("spu_id", spuId));
//        spuInfoDescEntity.setStatus(0);
//        spuInfoDescService.updateById(spuInfoDescEntity);
//        SpuImagesEntity spuImagesEntity = spuImagesService.getOne(new QueryWrapper<SpuImagesEntity>().eq("spu_id", spuId));
//        spuImagesEntity.setStatus(0);
//        spuImagesService.updateById(spuImagesEntity);
//
//        SkuInfoEntity skuInfo = skuInfoService.getOne(new QueryWrapper<SkuInfoEntity>().eq("spu_id", spuId));
//        skuInfo.setStatus(0);
//        skuInfoService.updateById(skuInfo);
//        SkuImagesEntity skuImagesServiceOne = skuImagesService.getOne(new QueryWrapper<SkuImagesEntity>().eq("spu_id", spuId));
//        skuImagesServiceOne.setStatus(0);
//        skuImagesService.updateById(skuImagesServiceOne);
//
//        ProductAttrValueEntity productAttrValueEntity = productAttrValueService.getOne(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id", spuId));
//        productAttrValueEntity.setStatus(0);
//        productAttrValueService.updateById(productAttrValueEntity);
//        SkuSaleAttrValueEntity skuSaleAttrValueEntity = saleAttrValueService.getOne(new QueryWrapper<SkuSaleAttrValueEntity>().eq("spu_id", spuId));
//        skuSaleAttrValueEntity.setStatus(0);
//        saleAttrValueService.updateById(skuSaleAttrValueEntity);
        return RespBean.success();
    }


    /**
     * 真实删除
     * @param spuId
     * @param memberId
     * @return
     */
    @Override
    public RespBean deleteProduct(long spuId, long memberId) {
        // TODO 真实删除  暂留

        return null;
    }


    /**
     * 远程调用专用，获取商品信息,创建订单的时候，调用
     *
     * @param spuId
     * @return
     */
    @Override
    public RespBean getSpuInfoVo(long spuId) {
        SpuInfoVo spuInfoVo = new SpuInfoVo();
        SpuInfoEntity spuInfo = this.getOne(new QueryWrapper<SpuInfoEntity>().eq("id", spuId));
        if (spuInfo == null) {
            throw new RRException("spu_id is exception at getMemberVo");
        }
        SkuInfoEntity skuInfo = skuInfoService.getOne(new QueryWrapper<SkuInfoEntity>().eq("spu_id", spuId));
        BrandEntity brand = brandService.getOne(new QueryWrapper<BrandEntity>().eq("brand_id", spuInfo.getBrandId()));
        SkuImagesEntity skuImagesEntity = skuImagesService.getOne(new QueryWrapper<SkuImagesEntity>().eq("sku_id", skuInfo.getSkuId()));
        List<SkuSaleAttrValueEntity> attrList = saleAttrValueService.list(new QueryWrapper<SkuSaleAttrValueEntity>().eq("sku_id", skuInfo.getSkuId()));
        SpuImagesEntity spuImages = spuImagesService.getOne(new QueryWrapper<SpuImagesEntity>().eq("spu_id", spuId));
        CategoryEntity category = categoryService.getOne(new QueryWrapper<CategoryEntity>().eq("category_id", spuInfo.getCatalogId()));

        List<String> list = new ArrayList<>();
        String attrValues = null;
        if (attrList == null || attrList.size() == 0) {
            attrValues = "";
        } else {
            for (SkuSaleAttrValueEntity saleAttrValueEntity : attrList) {
                list.add(saleAttrValueEntity.getAttrValue());
            }
            attrValues = JSON.toJSONString(list);
        }
        spuInfoVo.setAttrValues(attrValues);


        spuInfoVo.setSpuName(spuInfo.getSpuName());
        spuInfoVo.setSkuName(skuInfo.getSkuName());
        spuInfoVo.setSpuPic(spuImages.getImgUrl());
        spuInfoVo.setSkuPic(skuImagesEntity.getImgUrl());
        if (brand == null)
            spuInfoVo.setBrand("");
        else {
            spuInfoVo.setBrand(brand.getName());
        }
        if ( category == null ){
            spuInfoVo.setCategory("");
        }else {
            spuInfoVo.setCategory(category.getName());
        }
        spuInfoVo.setSpuDetail(spuInfo.getSpuDescription());
        spuInfoVo.setCategoryId(spuInfo.getCatalogId());

        spuInfoVo.setSkuId(skuInfo.getSkuId());
        spuInfoVo.setSkuPrice(skuInfo.getPrice());

        String jsonString = JSON.toJSONString(spuInfoVo);
        return RespBean.success().put("data", jsonString);
    }

    /**
     * 获取商品对应的会员id
     *
     * @param spuIds
     * @return
     */
    @Override
    public RespBean getMemberId(long[] spuIds) {

        FeignProductVo feignProductVo = new FeignProductVo();
        BigDecimal[] prices = new BigDecimal[spuIds.length];
        long[] memberIds = new long[spuIds.length];
        String[] names = new String[spuIds.length];
        String[] productNames = new String[spuIds.length];

        int index = -1;
        for (long spuId : spuIds) {
            MemberSpuEntity memberSpuEntity = memberSpuService.getOne(new QueryWrapper<MemberSpuEntity>().eq("spu_id", spuId));
            memberIds[++index] = memberSpuEntity.getMemberId();
            SkuInfoEntity skuInfo = skuInfoService.getOne(new QueryWrapper<SkuInfoEntity>().eq("spu_id", spuId));
            SpuInfoEntity spuInfo = this.getOne(new QueryWrapper<SpuInfoEntity>().eq("id", skuInfo.getSpuId()));

            BigDecimal price = skuInfo.getPrice();
            prices[index] = price;
            RespBean respBean = memberFeign.getMemberVo(memberSpuEntity.getMemberId());
            MemberVo memberVo = JSON.parseObject((String) respBean.get("data"), MemberVo.class);
            names[index] = memberVo.getUsername();
            productNames[index] = spuInfo.getSpuName();
        }
        feignProductVo.setMemberIds(memberIds);
        feignProductVo.setPrices(prices);
        feignProductVo.setNames(names);
        feignProductVo.setProductNames(productNames);

        String jsonString = JSON.toJSONString(feignProductVo);
        return RespBean.success().put("data", jsonString);
    }

    /**
     * 通过spuids获取相对于的商品
     *
     * @param spuIds
     * @return
     */
    @Override
    public RespBean getProductBySpuIds(long[] spuIds) {

        List<AllProductVo> allProductVoList = new ArrayList<>();
        List<SpuInfoEntity> list = new ArrayList<>();
        for (long spuId : spuIds) {
            // 判断是否在生成订单前被其他人已经提前购买
            String productToen = String.valueOf(new Sha256Hash(String.valueOf(spuId), AllSaltEnum.SALT.getSalt()));
            Integer saleCount = (Integer) redisTemplate.opsForValue().get("saleCount:" + productToen);
            if ( saleCount == null || saleCount != 0) {
                continue;
            }
            // 判断是否在生成订单前被下架
            SpuInfoEntity id = this.getOne(new QueryWrapper<SpuInfoEntity>().eq("id", spuId).eq("status", 1));
            if ( id == null ){
                continue;
            }
            if (id.getPublishStatus() != 1) {
                continue;
            }
            list.add(id);
        }
        Iterator<SpuInfoEntity> iterator = list.iterator();
        while (iterator.hasNext()) {
            SpuInfoEntity spuInfo = iterator.next();
            AllProductVo product = getProduct(spuInfo, iterator);
            MemberSpuEntity memberSpuEntity = memberSpuService.getOne(new QueryWrapper<MemberSpuEntity>()
                    .eq("spu_id", spuInfo.getId()).eq("status", 1));
            product.setMemberId(memberSpuEntity.getMemberId());
            allProductVoList.add(product);
        }
        return RespBean.success().put("data", allProductVoList);
    }


    /**
     * 更新所有的关于spu和sku的所有信息
     *
     * @param skuInfoDo
     * @param spuInfoDo
     * @param productInfoVo
     */
    private void updateSpuSkuInfo(SkuInfoEntity skuInfoDo, SpuInfoEntity spuInfoDo,
                                  ProductInfoVo productInfoVo) {
        String spuTitle = productInfoVo.getSpuTitle();
        String spuDetail = productInfoVo.getSpuDetail();
        BigDecimal price = productInfoVo.getPrice();
        String[] imageUrls = productInfoVo.getImageUrls();

        skuInfoDo.setSkuTitle(spuTitle);
        skuInfoDo.setSkuSubtitle(spuTitle);
        skuInfoDo.setSkuDesc(spuDetail);
        skuInfoDo.setPrice(price);
        SkuImagesEntity skuImagesEntity = skuImagesService.getOne(new QueryWrapper<SkuImagesEntity>()
                .eq("sku_id", skuInfoDo.getSkuId()));
        if (skuImagesEntity != null) {
            skuImagesEntity.setImgUrl(imageUrls[0]);
            skuImagesService.updateById(skuImagesEntity);
        }


        spuInfoDo.setSpuDescription(spuDetail);
        spuInfoDo.setUpdateTime(new Date());
        spuInfoDo.setSpuName(spuTitle);
        SpuImagesEntity spuImagesEntity = spuImagesService.getOne(new QueryWrapper<SpuImagesEntity>()
                .eq("spu_id", spuInfoDo.getId()));
        if (spuImagesEntity != null) {
            spuImagesEntity.setImgUrl(imageUrls[0]);
            spuImagesEntity.setImgName(spuTitle);
            spuImagesService.updateById(spuImagesEntity);
        }

        SpuInfoDescEntity spuInfoDescEntityDo = spuInfoDescService.getOne(new QueryWrapper<SpuInfoDescEntity>()
                .eq("spu_id", productInfoVo.getSpuId()));
        if (spuInfoDescEntityDo == null) {
            log.error("spu_id is exception");
            throw new RRException("spu_id is exception");
        }
        StringJoiner joiner = new StringJoiner("");
        for (String imageUrl : imageUrls) {
            joiner.add(imageUrl + ";");
        }
        spuInfoDescEntityDo.setDecript(String.valueOf(joiner));
        spuInfoDescService.updateById(spuInfoDescEntityDo);
    }


    /**
     * 更新该品牌旗下的商品名称
     *
     * @param productInfoVo
     */
    private void updateBrandSellName(SkuInfoEntity skuInfoDo, ProductInfoVo productInfoVo) {
        skuInfoDo.setBrandSellProductName(productInfoVo.getBrandSellName());
    }


    /**
     * 更新所有关于分类和品牌的表
     *
     * @param productInfoVo
     */
    private void updateCategoryBrand(
            SkuInfoEntity skuInfoDo, SpuInfoEntity spuInfoDo,
            ProductInfoVo productInfoVo) {
        // 判断分类是否发生改变或者之前是否进行分类
        // 判断品牌是否更新，或者是，是否清除
        // 为0 ，说明没有分类, 判断之前是否进行了分类，如果进行了分类，那么去除所有分类
        // 品牌同上理
        // 如果category_id相等，且那么肯定都为0，不用更新，如果不相等，那么之前有，清除之前所有的分类
        if (spuInfoDo.getCatalogId() != productInfoVo.getCategoryId()) {
            // 不相等，做更新操作---category
            spuInfoDo.setCatalogId((long) productInfoVo.getCategoryId());
            skuInfoDo.setCatalogId((long) productInfoVo.getCategoryId());
        }
        if (spuInfoDo.getBrandId() != productInfoVo.getBrandId()) {
            // 不相等，做更新操作---brand
            spuInfoDo.setBrandId((long) productInfoVo.getBrandId());
            skuInfoDo.setBrandId((long) productInfoVo.getBrandId());
        }
    }


    /**
     * 更新所有关于属性的表
     * 情况类推:
     * 1、在用户发布商品前没有添加属性，则直接对属性进行  1:[插入添加]
     * 2、在用户发布商品时，没有选中所有的属性，后来又全选了 【 那么就需要判断是 1:[插入和更新]   2:[只是更新]   3:[只是插入]  】
     * 3、用户没有传入数据， 1: [删除]
     * 4、用户传入了数据，但是只穿了一部分  1:[更新和删除]
     *
     * @param productInfoVo
     */
    private void updateAttr(ProductInfoVo productInfoVo) {
        // 更新需要的数据
        List<ProductAttrValueEntity> productAttrList = productAttrValueService.list(new QueryWrapper<ProductAttrValueEntity>()
                .eq("spu_id", productInfoVo.getSpuId()));
        List<SkuSaleAttrValueEntity> saleAttrList = saleAttrValueService.list(new QueryWrapper<SkuSaleAttrValueEntity>()
                .eq("sku_id", productInfoVo.getSkuId()));
        // 插入需要的数据
        Set<ProductAttrValueEntity> productAddSet = new HashSet<>();
        Set<SkuSaleAttrValueEntity> saleAttrAddSet = new HashSet<>();

        // 判断属性,更新productAttr表和sku_sale_attr表
        if (productInfoVo.getAllAttr().length > 0) {
            /**
             * 如果之前在发布商品时候没有进行属性的设置，当前修改则是进行属性的设置
             * 【 添加 】
             */
            if (productAttrList.size() <= 0) {

                for (int i = 0; i < productInfoVo.getAllAttr().length; i++) {
                    addAttr(
                            productInfoVo.getAllAttr()[i],
                            productInfoVo.getSpuId(), productInfoVo.getSkuId(),
                            productAddSet, saleAttrAddSet);
                }
            /**
             * 之前加入了数据,但是后来加入了更多的数据，两者数据不相等，那么进行插入和修改和删除，且传进来的大于数据库中的
             *      外部数据  >  数据库数据
             *     外部数据 1 2 3 4 5
             *     数据库数据 2 3 6
             *     最终数据为  1 2 3 4 5   // 删除 6
             * 【 更新 或 添加 或 删除 】
             */
            } else {

                boolean tag = false;   // 用以判断是否删除
                int index = -1;
                Iterator<ProductAttrValueEntity> iterator = productAttrList.iterator();
                Iterator<SkuSaleAttrValueEntity> iterator1 = saleAttrList.iterator();
                while (iterator.hasNext() && iterator1.hasNext()) {
                    ProductAttrValueEntity productAttrValueEntity = iterator.next();
                    SkuSaleAttrValueEntity saleAttrValueEntity = iterator1.next();
                    index++;
                    for (int i = 0; i < productInfoVo.getAllAttr().length; i++) {
                        // 如果数据库中的属性id和加入的属性id一样，那么就进行更新
                        if (productInfoVo.getAllAttr()[i].getId() == productAttrValueEntity.getAttrId()) {
                            updateAttr(productInfoVo.getAllAttr()[i], index, productAttrList, saleAttrList);
                            tag = true;
                            // 如果不相等，则进行添加
                        } else if (productInfoVo.getAllAttr()[i].getId() != productAttrValueEntity.getAttrId()) {
                            addAttr(
                                    productInfoVo.getAllAttr()[i],
                                    productInfoVo.getSpuId(),
                                    productInfoVo.getSkuId(),
                                    productAddSet, saleAttrAddSet
                            );
                        }
                    }
                    // 进行删除
                    if (tag) {
                        iterator.remove();
                        iterator1.remove();
                        productAttrValueService.removeById(productAttrValueEntity.getId());
                        saleAttrValueService.removeById(saleAttrValueEntity.getId());
                        index--;
//                        deleteAttr(index, productAttrList, saleAttrList);
                    }
                }
            }
            /**
             * 没有传入任何属性就是删除
             * 【 删除全部 】
             */
        } else if (productInfoVo.getAllAttr().length == 0) {
            for (int i = 0; i < productAttrList.size(); i++) {
                deleteAttr(i, productAttrList, saleAttrList);
            }
        }

        productAttrValueService.saveBatch(productAddSet);
        saleAttrValueService.saveBatch(saleAttrAddSet);

        productAttrValueService.updateBatchById(productAttrList);
        saleAttrValueService.updateBatchById(saleAttrList);


        // 更新自增主键
        List<ProductAttrValueEntity> list = productAttrValueService.list();
        List<SkuSaleAttrValueEntity> list1 = saleAttrValueService.list();


        for (int i = 0; i < list.size(); i++) {
            long productId = list.get(i).getId(), saleId = list1.get(i).getId();
            if ( productId !=  list.get(i).getId() ){
                spuInfoDao.updateId("pms_product_attr_value", (int) productId, (i+1));
            }
            if ( saleId != list1.get(i).getId() ){
                spuInfoDao.updateId("pms_sku_sale_attr_value", (int) saleId, (i+1));
            }
        }
        spuInfoDao.renewAutoIncrement("pms_sku_sale_attr_value", list1.size() + 1);
        spuInfoDao.renewAutoIncrement("pms_product_attr_value",list.size() + 1);
    }


    public void deleteAttr(int index, List<ProductAttrValueEntity> productAttrList, List<SkuSaleAttrValueEntity> saleAttrList) {

        productAttrValueService.remove(new QueryWrapper<ProductAttrValueEntity>().eq("id",
                productAttrList.get(index).getId()));

        saleAttrValueService.remove(new QueryWrapper<SkuSaleAttrValueEntity>().eq("id",
                saleAttrList.get(index).getId()));
    }

    public void updateAttr(AttrInfo attrInfo, int index, List<ProductAttrValueEntity> productAttrList, List<SkuSaleAttrValueEntity> saleAttrList) {
        // 更新id
        productAttrList.get(index).setAttrId((long) attrInfo.getId());
        saleAttrList.get(index).setAttrId((long) attrInfo.getId());
        // 更新name
        productAttrList.get(index).setAttrName(attrInfo.getName());
        saleAttrList.get(index).setAttrName(attrInfo.getName());
        // 更新值
        productAttrList.get(index).setAttrValue(attrInfo.getValue());
        saleAttrList.get(index).setAttrValue(attrInfo.getValue());
        // 更新状态
        productAttrList.get(index).setStatus(1);
        saleAttrList.get(index).setStatus(1);

    }


    /**
     * @param attrInfo        属性信息
     * @param spuId           商品id
     * @param skuId           skuId
     * @param productAttrList
     * @param saleAttrList
     */
    public void addAttr(AttrInfo attrInfo, long spuId, long skuId, Set<ProductAttrValueEntity> productAttrList, Set<SkuSaleAttrValueEntity> saleAttrList) {
        ProductAttrValueEntity productEntity = new ProductAttrValueEntity();
        SkuSaleAttrValueEntity saleEntity = new SkuSaleAttrValueEntity();
        // 加入attr的id
        productEntity.setAttrId((long) attrInfo.getId());
        saleEntity.setAttrId((long) attrInfo.getId());
        // 加入attr的name
        productEntity.setAttrName(attrInfo.getName());
        saleEntity.setAttrName(attrInfo.getName());
        // 加入attr的值
        productEntity.setAttrValue(attrInfo.getValue());
        saleEntity.setAttrValue(attrInfo.getValue());
        // 设置状态
        productEntity.setStatus(1);
        saleEntity.setStatus(1);
        // 设置spuid和skuid
        productEntity.setSpuId(spuId);
        saleEntity.setSkuId(skuId);
        //
        productEntity.setAttrSort(0);
        productEntity.setQuickShow(0);
        saleEntity.setAttrSort(0);

        productAttrList.add(productEntity);
        saleAttrList.add(saleEntity);
    }


    /**
     * 构建searchVo搜索项,
     *      商品插入或者更新或者删除的时候调用，，通过spuId和status进行修改
     * @param spuInfoEntity
     * @param open 表示是否启用
     */
    @Override
    public void createSearchVo(SpuInfoEntity spuInfo, boolean open){
        SearchResponseVo searchVo = new SearchResponseVo();
        List<ProductAttrValueEntity> attrList = productAttrValueService.list(new QueryWrapper<ProductAttrValueEntity>()
                .eq("spu_id", spuInfo.getId()));
        SpuImagesEntity spuImages = spuImagesService.getOne(new QueryWrapper<SpuImagesEntity>().eq("spu_id", spuInfo.getId()));
        SkuInfoEntity skuInfo = skuInfoService.getOne(new QueryWrapper<SkuInfoEntity>().eq("spu_id", spuInfo.getId()));
        SpuInfoDescEntity descEntity = spuInfoDescService.getOne(new QueryWrapper<SpuInfoDescEntity>().eq("spu_id", spuInfo.getId()));

        searchVo.setSpuId(spuInfo.getId());   // 设置spuId
        searchVo.setSpuImage(spuImages.getImgUrl());  // 设置展示图片
        searchVo.setSpuDetail(spuInfo.getSpuDescription());  // 设置商品详细介绍
        searchVo.setSpuTitle(spuInfo.getSpuName());  // 设置标题
        searchVo.setSpuPrice(skuInfo.getPrice().doubleValue());   // 设置价格
        searchVo.setImageUrls(descEntity.getDecript());  // 设置所有的图片  分号进行分割
        // 设置了分类的商品
        if ( spuInfo.getCatalogId() > 0 ){
            CategoryEntity category = categoryService.getOne(new QueryWrapper<CategoryEntity>().eq("category_id", spuInfo.getCatalogId()));
            searchVo.setCategory(category.getName());
            searchVo.setCategoryId(spuInfo.getCatalogId());
        }
        // 设置了品牌的商品
        if ( spuInfo.getBrandId() > 0 ){
            BrandEntity brand = brandService.getOne(new QueryWrapper<BrandEntity>().eq("brand_id", spuInfo.getBrandId()));
            searchVo.setBrand(brand.getName());
            searchVo.setBrandId(spuInfo.getBrandId());   // 品牌id
            searchVo.setBrandLog(brand.getLogo());   // 设置平拍log
        }
        // 设置了属性的商品
        List<Attrs> list = new ArrayList<>();
        Attrs attrs = null;
        if ( attrList != null && attrList.size() > 0 ){
            for (ProductAttrValueEntity attr : attrList) {
                attrs = new Attrs();
                attrs.setAttrId(attr.getAttrId());
                attrs.setAttrName(attr.getAttrName());
                attrs.setAttrValue(attr.getAttrValue());
                list.add(attrs);
            }
        }
        searchVo.setAttrs(list);   // 设置属性
        if( open ){
            searchVo.setStatus(1);  // 设置状态为 1 启用
        }else {
            searchVo.setStatus(0);   // 不启用
        }

        MemberSpuEntity memberSpuDo = memberSpuService.getOne(new QueryWrapper<MemberSpuEntity>()
                .eq("spu_id", spuInfo.getId()));
        searchVo.setMemberId(memberSpuDo.getMemberId());   // 设置发布者id

        RespBean respBean = memberFeign.getMemberVo(memberSpuDo.getMemberId());
        MemberVo memberVo = JSON.parseObject((String) respBean.get("data"), MemberVo.class);
        String nickname = memberVo.getUsername();
        searchVo.setNickname(nickname);   // 设置会员名称

        String jsonString = JSON.toJSONString(searchVo);
        // 发送监听消息
        rabbitTemplate.convertAndSend(RabbitMQConfit.INSERT_UPDATE_QUEUE, jsonString);
    }


    /**
     * 远程调用  判断该商品是否是自己发布的
     * @param memberId
     * @param spuId
     * @return
     */
    @Override
    public RespBean checkPublisherIsMyself(Long memberId, Long spuId) {
        Boolean isMyself = checkPublisherIsMyself(memberId, spuId, true);
        return RespBean.success().put("data", isMyself.toString());
    }


    /**
     * 远程调用，检查这些商品中是否有自己的商品,
     *   如果订单中有自己的商品，那么全部商品都不能购买
     *   需要用户自己去查找相应的
     *      创建订单是调用
     * @param spuIds
     * @param price
     * @return
     */
    @Override
    public RespBean batchCheckPublisherIsMyself(Long memberId, Long[] spuIds) {
        for (Long spuId : spuIds) {
            Boolean isMyself = checkPublisherIsMyself(memberId, spuId, false);
            // 如果是
            if( isMyself ){
                return RespBean.success().put("data", isMyself.toString());
            }
        }
        return RespBean.success().put("data", "false");
    }


    /**
     * 通用方法，抽取，防止冗余
     *      如果是自己的商品，那么返回true
     *      否则返回false
     * @param memberId
     * @param spuId
     * @return
     */
    public Boolean checkPublisherIsMyself(Long memberId, Long spuId, Boolean tag){
        // 通过member查中间表，用户id检测, 是否是自己发布的商品检测
        MemberSpuEntity memberSpu = memberSpuService.getOne(new QueryWrapper<MemberSpuEntity>().eq("member_id", memberId)
                .eq("status", 1).eq("spu_id", spuId));
        if ( memberSpu == null ){
            log.info("dvi1");
            return false;
        }
        // 创建订单时，不调用
        if ( tag ){
            // 商品redis库存检测
            String productToken = String.valueOf(new Sha256Hash(spuId.toString(), AllSaltEnum.SALT.getSalt()));
            Integer saleCount = (Integer) redisTemplate.opsForValue().get("saleCount:" + productToken);
            if ( saleCount == null || saleCount != 0 ){
                log.info("dvi2");
                return false;
            }
            // 商品id检测，上架检测
            SpuInfoEntity spuInfo = this.getOne(new QueryWrapper<SpuInfoEntity>().eq("id", memberSpu.getSpuId()));
            if ( spuInfo == null || !spuInfo.getId().equals(spuId) || spuInfo.getPublishStatus() != 1) {
                log.info("dvi3");
                return false;
            }
            // 商品数据库库存检测
            SkuInfoEntity skuInfo = skuInfoService.getOne(new QueryWrapper<SkuInfoEntity>().eq("spu_id", spuId));
            if ( skuInfo == null || skuInfo.getSaleCount() != 0 ){
                log.info("dvi4");
                return false;
            }
        }
        return true;
    }


    /**
     * 远程调用，检查总价是否一致, 由于在购买之前已经进行
     *  了库存的判断，所以这里直接进行金额计算即可
     *      创建订单调用
     * @param spuIds
     * @param price
     * @return
     */
    @Override
    public RespBean checkProductPrice(Long[] spuIds, BigDecimal price) {
        BigDecimal totalPrice = new BigDecimal(0);
        for (Long spuId : spuIds) {
            SkuInfoEntity skuInfo = skuInfoService.getOne(new QueryWrapper<SkuInfoEntity>().eq("spu_id", spuId));
            BigDecimal spuPrice = skuInfo.getPrice();
            totalPrice = totalPrice.add(spuPrice);
        }
        Double totalPrice1 = Double.valueOf(String.valueOf(totalPrice));
        Double price1 = Double.valueOf(String.valueOf(price));
        // 总价相同，返回true
        if ( totalPrice1.equals(price1) ){
            return RespBean.success().put("data", "true");
        }
        return RespBean.success().put("data", "false");
    }


    /**
     * 管理员。。。通过spuId将商品进行下架处理,,禁用/启用
     * @param spuId
     * @return
     */
    @Override
    public RespBean offShelfProduct(Long spuId, Integer status) {
        // 修改elasticSearch商品
        rabbitTemplate.convertAndSend(status==1?RabbitMQConfit.PRODUCT_RELEASE_QUEUE:RabbitMQConfit.PRODUCT_SELL_QUEUE,  spuId);

        // 修改redis中的商品
        String productToken = String.valueOf(new Sha256Hash(spuId.toString(), AllSaltEnum.SALT.getSalt()));

        Integer saleCount = (Integer) redisTemplate.opsForValue().get("saleCount:" + productToken);
        if ( saleCount != null ){
            if ( status == 1 ){
                if ( saleCount == 1 ){
                    redisTemplate.opsForValue().decrement("saleCount:" + productToken);
                }
            }else if (status ==0 ){
                if ( saleCount == 0){
                    redisTemplate.opsForValue().increment("saleCount:" + productToken);
                }
            }
        }
        // 修改数据库中的商品的删除状态
        SpuInfoEntity spuInfo = this.getOne(new QueryWrapper<SpuInfoEntity>().eq("id", spuId));
        spuInfo.setStatus(status);
        spuInfo.setUpdateTime(new Date());
        this.updateById(spuInfo);

        // 如果该商品用于展示，那么修改热点商品和轮播图信息
        updateCarousel(spuInfo, status);
        updateHotSpu(spuInfo, status);

        return RespBean.success();
    }

}
